package iso8583

import (
	"encoding/hex"
	"fmt"
	"strconv"
	"strings"

	"golang.org/x/text/encoding/simplifiedchinese"
)

//KidField61 域 61 持卡人身份认证信息 子域
type KidField61 struct {
	Parent           *Field            //父域
	KidID            *KidID            //61．1（证件编号）
	KidCVV           *KidVV            //61．2（CVV校验结果）
	KidPVV           *KidVV            //61．3（PVV校验结果）
	KidNoCardChValue *KidNoCardChValue //61．4（无卡校验值)
	KidARQCValue     *KidVV            //61．5（ARQC 认证结果值）
	KidSafeValue     *KidSafeValue61   //61．6（安全信息校验值）

}

//NewKidField61 初始化 第61域
func NewKidField61(p *Field) *KidField61 {
	kid61 := &KidField61{
		Parent:           p,
		KidID:            &KidID{Len: 22},
		KidCVV:           &KidVV{Len: 1},
		KidPVV:           &KidVV{Len: 1},
		KidNoCardChValue: &KidNoCardChValue{Len: 7},
		KidARQCValue:     &KidVV{Len: 1},
		KidSafeValue: &KidSafeValue61{
			Name: "KidSafeValue61",
			Len:  168,
		},
	}
	pos := NewPosion()
	data := p.Data

	KidID := kid61.KidID
	KidID.Data = data[pos.Get() : pos.Get()+KidID.Len]
	pos.Add(KidID.Len)
	KidID.parse()
	fmt.Printf("解析61域==》：%+v\n\t", KidID)
	KidCVV := kid61.KidCVV
	KidCVV.Data = data[pos.Get() : pos.Get()+KidCVV.Len]
	pos.Add(KidCVV.Len)
	KidCVV.parse()
	fmt.Printf("解析61域==》：%+v\n\t", KidCVV)
	KidPVV := kid61.KidPVV
	KidPVV.Data = data[pos.Get() : pos.Get()+KidPVV.Len]
	pos.Add(KidPVV.Len)
	KidPVV.parse()
	fmt.Printf("解析61域==》：%+v\n\t", KidPVV)
	KidNoCardChValue := kid61.KidNoCardChValue
	KidNoCardChValue.Data = data[pos.Get() : pos.Get()+KidNoCardChValue.Len]
	pos.Add(KidNoCardChValue.Len)
	KidNoCardChValue.parse()
	fmt.Printf("解析61域==》：%+v\n\t", KidNoCardChValue)
	KidARQCValue := kid61.KidARQCValue
	KidARQCValue.Data = data[pos.Get() : pos.Get()+KidARQCValue.Len]
	pos.Add(KidARQCValue.Len)
	KidARQCValue.parse()
	fmt.Printf("解析61域==》：%+v\n\t", KidARQCValue)
	KidSafeValue := kid61.KidSafeValue

	KidSafeValue.Data = data[pos.Get():]
	//pos.Add(KidARQCValue.Len)
	KidSafeValue.parse()
	fmt.Printf("解析61域==》：%+v\n\t", KidSafeValue)
	return kid61
}

//KidID 证件号
type KidID struct {
	Type string
	vaue string
	Data []byte
	Len  int
}

func (kid *KidID) parse() {

	mark := kid.Data[:2]
	value := kid.Data[2:]
	kid.vaue = strings.TrimSpace(string(value))
	kid.Type = string(mark)
}

//KidVV 校验值
type KidVV struct {
	vaue string
	Len  int
	Data []byte
}

func (kid *KidVV) parse() {
	kid.vaue = strings.TrimSpace(string(kid.Data))
}

//KidNoCardChValue 无卡校验值
type KidNoCardChValue struct {
	Len    int
	Type   string
	vaue   string
	Result string
	Data   []byte
}

func (kid *KidNoCardChValue) parse() {
	data := kid.Data
	kid.Type = strings.TrimSpace(string(data[:3]))
	kid.vaue = strings.TrimSpace(string(data[3:6]))
	kid.Result = strings.TrimSpace(string(data[6:]))
}

//KidSafeValue61 域安全信息校验值
type KidSafeValue61 struct {
	Name  string //名称
	Len   int    //字节长度
	Data  []byte //字节数据
	KidID string //标志
	Typ   string //用法格式
	Sc    SCType
	Ar    ARType
	Sa    SAType
	Cr    CRType
	Am    AMType
	Nm    NMType
}

//newKidSafeValue61 创建61域子域中安全信息校验值
func newKidSafeValue61(len int, data []byte) *KidSafeValue61 {
	return &KidSafeValue61{
		Name: "KidSafeValue61",
		Len:  len,
		Data: data,
	}
}
func (kid *KidSafeValue61) parse() {
	p := NewPosion()
	data := kid.Data
	kid.KidID = string(data[:3])
	p.Add(3)
	kid.Typ = string(data[p.Get() : p.Get()+2])
	p.Add(2)

	switch kid.Typ {
	case "AM":
		am := newAMType()
		//截取位图
		bitM := data[p.Get() : p.Get()+16]
		p.Add(16)
		//解析位图
		for i := 0; i < 16; i++ {
			bb := bitM[i]
			if bb&0x01 > 0 {
				am.BitMap[i+1] = i + 1
			}
		}
		for _, vaue := range am.BitMap {
			switch vaue {
			case 1:
				fmt.Println("密码验证（密码存放在52域53域中）")
			case 2:
				fmt.Println("卡有效期验证（卡有效期信息存放在 14 域之中）")
			case 3:
				fmt.Println("身份证件验证（身份证件信息存放在 61.1 域之中）")

			case 4, 5, 7, 13, 14, 15, 16:
				fmt.Println("保留使用，用全零填充")
			case 6:
				fmt.Println("CVN2 验证（CVN2 信息存放在 61.4 域之中）")
			case 8:
				fmt.Println("姓名验证（姓名信息存放在本用法之中）")
				//获取姓名字节长度3个字节
				nameSize := data[p.Get() : p.Get()+3]
				p.Add(3)
				size, err := strconv.Atoi(string(nameSize))
				if err == nil {
					name := data[p.Get() : p.Get()+size]
					p.Add(size)
					reader, err := simplifiedchinese.GB18030.NewDecoder().Bytes(name)
					if err == nil {
						am.Name = string(reader)
					}

				}
			case 9:
				fmt.Println("手机号码验证（手机号码信息存放在本用法之中）", string(data))
				//获取姓名字节长度3个字节
				mobileSize := data[p.Get() : p.Get()+3]
				p.Add(3)
				size, err := strconv.Atoi(string(mobileSize))
				if err == nil {
					mobile := string(data[p.Get() : p.Get()+size])
					p.Add(size)
					am.Mobile = mobile
				}
			case 10:
				fmt.Println("动态验证码验证（动态验证码信息存放在本用法之中）")
				//获取姓名字节长度3个字节
				verifySize := data[p.Get() : p.Get()+3]
				p.Add(3)
				size, err := strconv.Atoi(string(verifySize))
				if err == nil {
					verifyCode := data[p.Get() : p.Get()+size]
					key := string(verifyCode[:20])
					am.Key = key
					p.Add(size)
					am.VerifyCode = strings.TrimSpace(string(verifyCode[20:]))
				}
			case 11:
				fmt.Println("保留（3DS2.0 专用，参见《3DS2.0 项目技术实施指南》）")
			case 12:
				fmt.Println(`委托关系验证（委托关系要素包括但不限于
				持卡人卡号、商户代码、用户号码、商户名称、用户
				号码类型、代收频率、委托关系限期、最高限制金
				额、最低限制金额等基本要素；委托关系以持卡人卡
				号、商户代码、用户号码作为主键）`)
			}

		}

		kid.Am = *am
	case "SC", "AR", "SA", "CR", "NM":
		fmt.Println("为实现此用法解析", kid.Typ)
	}
}

// SC 用法一 表示银联安全输入模式
// AR 用法二 表示在银联安全输入模式下发卡机构的认证结果
// SA 用法三 表示发卡机构直接身份认证模式
// CR 用法四 表示在发卡机构直接身份认证模式下发卡机构对 CAVV 值的认证 结果
// AM 用法五 表示交易过程中受理方要求发卡方校验的方式
// NM 用法六 持卡人姓名

//SCType 表示银联安全输入模式
type SCType struct {
}

//ARType 表示在银联安全输入模式下发卡机构的认证结果
type ARType struct {
}

//SAType 表示发卡机构直接身份认证模式
type SAType struct {
}

//CRType 表示在发卡机构直接身份认证模式下发卡机构对 CAVV 值的认证
type CRType struct {
}

//AMType 表示交易过程中受理方要求发卡方校验的方式
type AMType struct {
	BitMap     []int //位图构造
	Name       string
	Mobile     string
	Key        string //校验码
	VerifyCode string //动态验证码
}

func newAMType() *AMType {
	return &AMType{
		BitMap: make([]int, 17),
	}
}

//NMType 持卡人姓名
type NMType struct {
}

//Field61 字符数字
type Field61 struct {
	Field
	Kid KidField61
}

//NewField61 61域解析
//域 61 持卡人身份认证信息 ans...200(LLLVAR)，3个字节的长度值＋最大200个字节(字母、数字和特殊字符)的持卡人身份认
func NewField61(name int, typ int, len int) *Field61 {
	return &Field61{
		Field: Field{
			Name:   name,
			Type:   typ,
			Len:    len,
			PadMod: RightPad,
		},
	}
}

//Name 获取名称
func (f *Field61) Name() int {
	return f.Field.Name
}

//ValueString 真值
func (f *Field61) ValueString() string {
	return f.Field.DataStr
}

//Format 格式化域更具情况填充域值
func (f *Field61) Format() []byte {
	if f.Field.Type == FIX {
		//如果是右靠齐就是填充左边
		l := f.Field.Len
		if f.PadMod == LeftPad {
			f.Field.Data = LeftPading(f.Field.Data, l, BLANK)
		} else if f.PadMod == RightPad {
			f.Field.Data = RightLading(f.Field.Data, l, BLANK)
		}
	}
	return f.Field.Data
}

//Parse 解析
func (f *Field61) Parse(b []byte, pos *Position) string {
	//获取2个字节的长度值
	len := f.Type
	size := b[pos.Get() : pos.Get()+len]
	pos.Add(len)
	if strLen, err := strconv.Atoi(string(size)); err == nil {
		dist := make([]byte, strLen)
		copy(dist, b[pos.Get():pos.Get()+strLen])
		pos.Add(strLen)
		f.Data = dist
		f.DataStr = string(f.Data)
		f.Kid = *NewKidField61(&f.Field)

	} else {
		fmt.Printf("解析域出现错误：%+v\n\t", err.Error())
	}

	fmt.Printf("解析域（%d）完毕：%+v\n\t", f.Field.Name, f)

	return f.DataStr
}

//Field43 解析43域
type Field43 struct {
	Field
}

//NewField43 解析43域
func NewField43(name int, typ int, len int) *Field43 {
	return &Field43{
		Field: Field{
			Name:   name,
			Type:   typ,
			Len:    len,
			PadMod: RightPad,
		},
	}
}

//Name 获取名称
func (f *Field43) Name() int {
	return f.Field.Name
}

//ValueString 真值
func (f *Field43) ValueString() string {
	return f.Field.DataStr
}

//Format 格式化域更具情况填充域值
func (f *Field43) Format() []byte {
	if f.Field.Type == FIX {
		//如果是右靠齐就是填充左边
		l := f.Field.Len
		if f.PadMod == LeftPad {
			f.Field.Data = LeftPading(f.Field.Data, l, BLANK)
		} else if f.PadMod == RightPad {
			f.Field.Data = RightLading(f.Field.Data, l, BLANK)
		}
	}
	return f.Field.Data
}

//Parse 解析
func (f *Field43) Parse(b []byte, pos *Position) string {
	dist := make([]byte, f.Len)
	copy(dist, b[pos.Get():pos.Get()+f.Len])
	pos.Add(f.Len)
	f.Data = dist

	reader, err := simplifiedchinese.GB18030.NewDecoder().Bytes(f.Data)
	if err != nil {
		f.DataStr = string(f.Data)
	} else {
		f.DataStr = string(reader)
	}

	return f.DataStr
}

//Feild125 域125解析
type Feild125 struct {
	Field
	TLV map[string]Tlv
}

//Tlv 多用途子域
type Tlv struct {
	Data     []byte
	Tag      string
	Len      int
	Value    string
	KidTag   string
	KidLen   int
	KidValue string
}

func (tlv *Tlv) parseTag() {
	switch tlv.Tag {
	case "QP":
		dist := tlv.Data
		//子tlv 解析
		p := NewPosion()
		if dist[0]&0x01f == 0x01f {
			//说明tag长度占用2个字节
			kidT := dist[p.Get() : p.Get()+2]
			p.Add(2)
			tlv.KidTag = hex.EncodeToString(kidT)
		} else {
			//tag占用一个字节
			kidT := dist[p.Get() : p.Get()+1]
			p.Add(1)
			tlv.KidTag = hex.EncodeToString(kidT)
		}
		if dist[p.Get()]&0x80 == 0 {
			//占用一个字节
			len := int(uint(dist[p.Get()]))
			p.Add(1)
			tlv.KidLen = len
		} else {
			l := int(uint(dist[p.Get()] & (0x80 - 1)))
			p.Add(1)
			size := string(dist[p.Get() : p.Get()+l])
			p.Add(l)
			if strLen, err := strconv.Atoi(string(size)); err == nil {
				tlv.KidLen = strLen
			}
		}
		kidV := dist[p.Get() : p.Get()+tlv.KidLen]
		tlv.KidValue = string(kidV)
		fmt.Printf("tlv%+v", tlv)
	default:
		fmt.Println(tlv.Tag, "此方法使用为解析")
	}
}
func (f *Feild125) parseKid() {
	data := f.Data
	p := NewPosion()
	for len(data)-p.Get() > 0 {
		tlv := &Tlv{}
		tag := data[p.Get() : p.Get()+2]
		p.Add(2)
		size := data[p.Get() : p.Get()+3]
		p.Add(3)
		if strLen, err := strconv.Atoi(string(size)); err == nil {
			dist := make([]byte, strLen)
			copy(dist, data[p.Get():p.Get()+strLen])
			p.Add(strLen)
			tlv.Data = dist
			tlv.Len = strLen
			tlv.Value = string(dist)
			tlv.Tag = string(tag)
			//子tlv 解析
			tlv.parseTag()
			f.TLV[tlv.Tag] = *tlv
		} else {
			fmt.Printf("解析域出现错误：%+v\n\t", err.Error())
		}
	}

}

//NewFeild125 解析43域
func NewFeild125(name int, typ int, len int) *Feild125 {
	return &Feild125{
		TLV: make(map[string]Tlv),
		Field: Field{
			Name:   name,
			Type:   typ,
			Len:    len,
			PadMod: RightPad,
		},
	}
}

//Name 获取名称
func (f *Feild125) Name() int {
	return f.Field.Name
}

//ValueString 真值
func (f *Feild125) ValueString() string {
	return f.Field.DataStr
}

//Format 格式化域更具情况填充域值
func (f *Feild125) Format() []byte {

	return f.Field.Data
}

//Parse 解析
func (f *Feild125) Parse(b []byte, pos *Position) string {
	//获取2个字节的长度值
	len := f.Type
	size := b[pos.Get() : pos.Get()+len]
	pos.Add(len)
	if strLen, err := strconv.Atoi(string(size)); err == nil {
		dist := make([]byte, strLen)
		copy(dist, b[pos.Get():pos.Get()+strLen])
		pos.Add(strLen)
		f.Data = dist
		f.DataStr = string(f.Data)
		f.parseKid()
	} else {
		fmt.Printf("解析域出现错误：%+v\n\t", err.Error())
	}

	fmt.Printf("解析域（%d）完毕：%+v\n\t", f.Field.Name, f)

	return f.DataStr
}

func init() {
	Register(61, NewField61(61, LLLVAR, 203))    //域 61 持卡人身份认证信息 ans...200(LLLVAR)，3个字节的长度值＋最大200个字节(字母、数字和特殊字符)的持卡人身份认
	Register(43, NewField43(43, FIX, 40))        //域 43 受卡方名称地址，ans40，40位定长的字母、数字和特殊字符
	Register(125, NewFeild125(125, LLLVAR, 259)) //域 125 附加信息，ansb…256（LLLVAR），3字节长度值＋最大256个字节(字母、数字和特殊字符)的数据

}
